import { SignalMessage } from "../type";
import { SignalClient } from "./signal-client";
import { PeerConnectionManager } from "./peer-connection-manager";

export class SignalHandler {
  private signalClient: SignalClient;
  private peerConnectionManager: PeerConnectionManager;
  private onJoined?:(clientId: string, roomId: string) => void;

  constructor(
    signalClient: SignalClient,
    peerConnectionManager: PeerConnectionManager,
    onJoined?:(clientId: string, roomId: string) => void
  ) {
    this.signalClient = signalClient;
    this.peerConnectionManager = peerConnectionManager;
    this.onJoined = onJoined;
  }

  public handleMessage(msg: SignalMessage): void {
    switch (msg.type) {
      case "joined":
        console.log(msg.clientId," already joined the room", msg.roomId);
        this.onJoined?.(msg.clientId, msg.roomId);
        break;
      case "offer":
        console.log(
          "received offer from:",
          msg.from,
          "msg content:",
          msg.payload
        );
        this.handleOffer(msg);
        break;
      case "answer":
        console.log(
          "received answer from:",
          msg.from,
          "msg content:",
          msg.payload
        );
        this.handleAnswer(msg);
        break;
      case "other_joined":
        console.log("other joined:", msg.joinerId);
        this.handleOtherJoined(msg);
        break;
      case "candidate":
        console.log(
          "received candidate from:",
          msg.from,
          "msg content:",
          msg.payload
        );
        this.handleCandidate(msg);
        break;
      default:
        console.error("unknown message type:", msg.type);
        break;
    }
  }

  private async handleOffer(msg: SignalMessage) {
    if (!(msg.type === "offer" && msg.payload && msg.from)) {
      console.error("Invalid offer message:", msg);
      return;
    }
    await this.peerConnectionManager.setRemoteDescription(msg.payload);
    const answer = await this.peerConnectionManager.createAnswer();
    this.signalClient.send({
      type: "answer",
      from: msg.to,
      to: msg.from,
      payload: answer,
      roomId: msg.roomId,
    } as SignalMessage);
  }

  private async handleAnswer(msg: SignalMessage) {
    if (!(msg.type === "answer" && msg.payload && msg.from)) {
      console.error("Invalid answer message:", msg);
      return;
    }
    await this.peerConnectionManager.setRemoteDescription(msg.payload);
  }

  private async handleOtherJoined(msg: SignalMessage) {
    if (!(msg.type === "other_joined" && msg.joinerId && msg.roomId)) {
      console.error("Invalid other_joined message:", msg);
      return;
    }
    const offer = await this.peerConnectionManager.createOffer();
    this.signalClient.send({
      type: "offer",
      from: msg.to,
      to: msg.joinerId,
      payload: offer,
      roomId: msg.roomId,
    } as SignalMessage);
  }

  private async handleCandidate(msg: SignalMessage) {
    if (!(msg.type === "candidate" && "from" in msg && "payload" in msg)) {
      console.error("Invalid candidate message:", msg);
      return;
    }
    await this.peerConnectionManager.addIceCandidate(msg.payload);
  }
}
